package org.smartagents.body;

import org.smartagents.global.GlobalConstants;
import org.smartagents.global.Trigerable;
import org.smartagents.util.Logger;
import org.smartagents.enviro.EnvironmentConstants;

import java.util.List;
import java.util.ArrayList;

public class Neurone extends Trigerable {

    private String lastImpulse;

    private List<Trigerable> links;

    public void trigger(String impulse) {
        if (!impulse.equals(lastImpulse)) {
            lastImpulse = impulse;
            if (links != null) {
                for (Trigerable neurone : links) {
                    if (neurone.isSatisfied(neurone.getLinkCondition(), impulse)) {
                        if (impulse.equals(GlobalConstants.RESET_IMPULSE)) {
                            neurone.trigger("");
                        } else if (getAddBeforeSlot()==null)  {
                            neurone.trigger(impulse);
                        } else {
                            neurone.trigger(getAddBeforeSlot()+"|"+impulse);
                        }
                    } 
                }
            }
        } 
    }

    @Override
    public void tick() {

    }

    public void addLink(Trigerable neurone) {
        if (links == null) {
            links = new ArrayList();
        }

        links.add(neurone);
    }

    public List<Trigerable> getLinks() {
        return links;
    }

    public void setLinks(List<Trigerable> links) {
        this.links = links;
    }

    public String getLastImpulse() {
        return lastImpulse;
    }

    public void setLastImpulse(String lastImpulse) {
        this.lastImpulse = lastImpulse;
    }

    public String getChids(int level, List<Trigerable> knownNodes) {

        if (knownNodes == null) {
            knownNodes = new ArrayList<Trigerable>();
            knownNodes.add(this);
        }
        StringBuffer buf = new StringBuffer();
        addToBuffer(buf, level);
        buf.append(" ").append(getHash()).append(" [").append(getLinkCondition()).append("-").append(getAddBeforeSlot()).append("] \n");
        if (links != null && links.size() != 0) {
            for (Trigerable neu : links) {
                if (knownNodes.contains(neu)) {
                    addToBuffer(buf, level);
                    buf.append(" *").append(neu.getHash()).append(" [").append(neu.getLinkCondition()).append("-").append(neu.getAddBeforeSlot()).append("] \n");
                } else {
                    if (neu instanceof Neurone) {
                        buf.append(((Neurone) neu).getChids(level + 1, knownNodes));
                        knownNodes.add(neu);
                    }

                }
            }
        }

        return buf.toString();

    }

    public void getLinks(List<Trigerable> knownNodes) {

        if (knownNodes == null) {
            knownNodes = new ArrayList<Trigerable>();
            knownNodes.add(this);
        }

        if (links != null && links.size() != 0) {
            for (Trigerable neu : links) {
                if (!knownNodes.contains(neu)) {
                    if (neu instanceof Neurone) {
                        ((Neurone)neu).getLinks(knownNodes);
                        knownNodes.add(neu);
                    }

                }
            }
        }
    }

    public String getCode() {
        StringBuffer buf = new StringBuffer();
        List<Trigerable> neus = new ArrayList<Trigerable>();
        neus.add(this);
        this.getLinks(neus);
        int i=0;
        for (Trigerable neu : neus) {
            if (i++>0) {
                buf.append(EnvironmentConstants.NEURONE_SEPARATOR);
            }
            buf.append(neu.getHash()).append(EnvironmentConstants.NEURONE_DETAIL_SEPARATOR).append(neu.getLinkCondition());
            if (neu.getAddBeforeSlot()!=null) {
                buf.append(EnvironmentConstants.NEURONE_CONVERT_SEPARATOR).append(neu.getAddBeforeSlot());
            }
            if (((Neurone)neu).getLinks()!=null) {
                for (Trigerable links: ((Neurone)neu).getLinks()) {
                    buf.append(EnvironmentConstants.NEURONE_DETAIL_SEPARATOR).append(links.getHash());
                }
            }
        }

        return buf.toString();

    }

    private void addToBuffer(StringBuffer b, int level) {
        for (int i = 0; i < level; i++) {
            b.append("-");
        }
    }

}
